//
// Created by lidongwei on 2023-05-16.
//
#include "gpio.h"
#include "Delay.h"
#include "oled.h"
#include "i2c.h"

// 是否使用软件IIC驱动：0否，1是
char isSw = 0;

// 硬件驱动IIC
uint8_t u8x8_byte_hw_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
    /* u8g2/u8x8 will never send more than 32 bytes between START_TRANSFER and END_TRANSFER */
    static uint8_t buffer[128];
    static uint8_t buf_idx;
    uint8_t *data;

    switch (msg)
    {
        case U8X8_MSG_BYTE_INIT:
        {
            /* add your custom code to init i2c subsystem */
            MX_I2C1_Init(); //I2C初始化
        }
            break;

        case U8X8_MSG_BYTE_START_TRANSFER:
        {
            buf_idx = 0;
        }
            break;

        case U8X8_MSG_BYTE_SEND:
        {
            data = (uint8_t *)arg_ptr;

            while (arg_int > 0)
            {
                buffer[buf_idx++] = *data;
                data++;
                arg_int--;
            }
        }
            break;

        case U8X8_MSG_BYTE_END_TRANSFER:
        {
            if (HAL_I2C_Master_Transmit(&hi2c1, OLED_ADDRESS, buffer, buf_idx, 1000) != HAL_OK)
                return 0;
        }
            break;

        case U8X8_MSG_BYTE_SET_DC:
            break;

        default:
            return 0;
    }

    return 1;
}

uint8_t u8x8_gpio_and_delay(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
    switch (msg)
    {
        case U8X8_MSG_DELAY_100NANO: // delay arg_int * 100 nano seconds
            __NOP();
            break;
        case U8X8_MSG_DELAY_10MICRO: // delay arg_int * 10 micro seconds
            for (uint16_t n = 0; n < 320; n++)
            {
                __NOP();
            }
            break;
        case U8X8_MSG_DELAY_MILLI: // delay arg_int * 1 milli second
            delay_ms(1);
            break;
        case U8X8_MSG_DELAY_I2C: // arg_int is the I2C speed in 100KHz, e.g. 4 = 400 KHz
            delay_us(5);
            break;                    // arg_int=1: delay by 5us, arg_int = 4: delay by 1.25us
        case U8X8_MSG_GPIO_I2C_CLOCK: // arg_int=0: Output low at I2C clock pin
            if (isSw == 1)
            {
                if(arg_int == 1)
                {
                    HAL_GPIO_WritePin(IIC_GPIO_Port, SCL_Pin, GPIO_PIN_SET);
                }
                else if(arg_int == 0)
                {
                    HAL_GPIO_WritePin(IIC_GPIO_Port, SCL_Pin, GPIO_PIN_RESET);
                }
            }
            break;                    // arg_int=1: Input dir with pullup high for I2C clock pin
        case U8X8_MSG_GPIO_I2C_DATA:  // arg_int=0: Output low at I2C data pin
            if (isSw == 1)
            {
                if(arg_int == 1)
                {
                    HAL_GPIO_WritePin(IIC_GPIO_Port, SDA_Pin, GPIO_PIN_SET);
                }
                else if(arg_int == 0)
                {
                    HAL_GPIO_WritePin(IIC_GPIO_Port, SDA_Pin, GPIO_PIN_RESET);
                }
            }
            break;                    // arg_int=1: Input dir with pullup high for I2C data pin
        case U8X8_MSG_GPIO_MENU_SELECT:
            u8x8_SetGPIOResult(u8x8, /* get menu select pin state */ 0);
            break;
        case U8X8_MSG_GPIO_MENU_NEXT:
            u8x8_SetGPIOResult(u8x8, /* get menu next pin state */ 0);
            break;
        case U8X8_MSG_GPIO_MENU_PREV:
            u8x8_SetGPIOResult(u8x8, /* get menu prev pin state */ 0);
            break;
        case U8X8_MSG_GPIO_MENU_HOME:
            u8x8_SetGPIOResult(u8x8, /* get menu home pin state */ 0);
            break;
        default:
            u8x8_SetGPIOResult(u8x8, 1); // default return value
            break;
    }
    return 1;
}

/**
 * U8g2的初始化，需要调用下面这个u8g2_Setup_ssd1306_128x64_noname_f函数，该函数的4个参数含义：
 * u8g2：传入的U8g2结构体
 * U8G2_R0：默认使用U8G2_R0即可（用于配置屏幕是否要旋转）
 * u8x8_byte_sw_i2c：使用软件IIC驱动，该函数由U8g2源码提供
 * u8x8_gpio_and_delay：就是上面我们写的配置函数
 * @param u8g2
 */
void u8g2Init(u8g2_t *u8g2)
{
    u8g2_Setup_ssd1306_i2c_128x64_noname_f(u8g2, U8G2_R0, isSw == 1 ? u8x8_byte_sw_i2c : u8x8_byte_hw_i2c, u8x8_gpio_and_delay);  // 初始化 u8g2 结构体
    u8g2_InitDisplay(u8g2); // 根据所选的芯片进行初始化工作，初始化完成后，显示器处于关闭状态
    u8g2_SetPowerSave(u8g2, 0); // 打开显示器
    u8g2_ClearBuffer(u8g2);
}





